package model;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import model.Actions.addCharacterCommentAction;
import model.Actions.addFavoriteToDBAction;
import model.Actions.addNewCharacterReviewAction;
import model.Actions.addNewCharacterToDBAction;
import model.Actions.addNewUserToDBAction;
import model.Actions.addUserLegenDateAction;
import model.Actions.getBottomTenCharactersAction;
import model.Actions.getCharacterDetailsAction;
import model.Actions.getCharacterReviewsAction;
import model.Actions.getSearchResultsAction;
import model.Actions.getTopTenCharactersAction;
import model.Actions.getTopTenReviewedCharactersAction;
import model.Actions.getUserFavoritesAction;
import model.Actions.importCharacterCommentsAction;
import model.Actions.importUserLegenDatesAction;
import model.Actions.removeFavoriteFromDBAction;
import model.Actions.updateUserInDBAction;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import DB.Connection.DBConnectionManager;
import DB.FreeBaseImport.FreeBaseImport;

import commons.Constants;
import commons.Entities.Comment;
import commons.Entities.LegenCharacter;
import commons.Entities.LegenDate;
import commons.Entities.Review;
import commons.Entities.User;

public class ModelFunctions {

	private static final Log logger = LogFactory.getLog(ModelFunctions.class);

	private Executor taskExecutor;

	private final static ModelFunctions INSTANCE = new ModelFunctions();

	public static ModelFunctions get() {
		return INSTANCE;
	}

	public ModelFunctions() {
		logger.debug("Initializing ModelFunctions' taskExecutor.");

		taskExecutor = Executors.newFixedThreadPool(Constants.MODEL_FUNCTIONS_MAX_THREADS);

		logger.debug("ModelFunctions' TaskExecutor initialized successfully.");
	}

	public User getUserFromDB(String username) {
		return DBConnectionManager.get().findUserByName(username);
	}

	public void getUserFavoritesFromDB(Integer userID) {
		taskExecutor.execute(new getUserFavoritesAction(userID));
	}

	public void addFavoriteToDB(Integer userID, Integer characterID) {
		taskExecutor.execute(new addFavoriteToDBAction(userID, characterID));
	}

	public void removeFavoriteFromDB(Integer userID, Integer characterID) {
		taskExecutor.execute(new removeFavoriteFromDBAction(userID, characterID));
	}

	public void addNewUserToDB(User user) {
		taskExecutor.execute(new addNewUserToDBAction(user));
	}

	public void updateUserInDB(User user) {
		taskExecutor.execute(new updateUserInDBAction(user));
	}

	public void importUserLegenDates(Integer userID) {
		taskExecutor.execute(new importUserLegenDatesAction(userID));
	}

	public void addUserLegenDate(LegenDate legenDate) {
		taskExecutor.execute(new addUserLegenDateAction(legenDate));
	}

	public void getCharacterFromDB(Integer characterID) {
		taskExecutor.execute(new getCharacterDetailsAction(characterID));
	}

	public void addNewCharacterToDB(LegenCharacter legenCharacter) {
		taskExecutor.execute(new addNewCharacterToDBAction(legenCharacter));
	}

	public void importCharacterComments(Integer characterID) {
		taskExecutor.execute(new importCharacterCommentsAction(characterID));
	}

	public void addCharacterComment(Comment comment) {
		taskExecutor.execute(new addCharacterCommentAction(comment));
	}

	public void getSearchResults(String characterName, String gender, String species) {
		taskExecutor.execute(new getSearchResultsAction(characterName, gender, species));
	}

	public void addNewCharacterReview(Review review) {
		taskExecutor.execute(new addNewCharacterReviewAction(review));
	}

	public void getCharacterReview(Integer characterID) {
		taskExecutor.execute(new getCharacterReviewsAction(characterID));
	}

	public void getTopTenCharacters() {
		taskExecutor.execute(new getTopTenCharactersAction());
	}

	public void getBottomTenCharacters() {
		taskExecutor.execute(new getBottomTenCharactersAction());
	}

	public void getTopTenReviewedCharacters() {
		taskExecutor.execute(new getTopTenReviewedCharactersAction());
	}

	public boolean checkIfDateIsTaken(LegenDate legenDate) {
		return DBConnectionManager.get().checkIfDateIsTaken(legenDate);
	}

	public void updateDBFromFreebase() {
		taskExecutor.execute(new FreeBaseImport(true));
	}
}
